package pres.liko.iot.gateway.filters;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import pres.liko.iot.gateway.config.IpsCacheConfig;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.Set;

/**
 * @ClassName: BlackIpGlobalFilter
 * @Auther: liko
 * @Description:
 * @Date: 2022/11/1 22:50
 */
@Component
public class BlackIpGlobalFilter implements Ordered, GlobalFilter {

    private IpsCacheConfig ipsCacheConfig;

    @Autowired
    public BlackIpGlobalFilter(IpsCacheConfig ipsCacheConfig) {
        this.ipsCacheConfig = ipsCacheConfig;
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 获取用户ip
        String host = exchange.getRequest().getLocalAddress().getHostString();
        // 获取到所有的ip黑名单
        Set<String> blackips = ipsCacheConfig.getBlackcache();
        
        return Mono.just(blackips)
                // 判断是否在黑名单中
                // 空集合的contains返回false
                .filter(strings -> !strings.contains(host))
                // 根据结果来决定是否放行
                .map(strings -> chain.filter(exchange))// 不在黑名单的人放行
                .defaultIfEmpty(
                        exchange.getResponse().writeAndFlushWith(
                                Mono.just(
                                        Mono.just(
                                                DefaultDataBufferFactory
                                                        .sharedInstance
                                                        .allocateBuffer()
                                                        .write("非法登录，请联系管理员".getBytes(StandardCharsets.UTF_8))
                                        )
                                )
                        )
                ).flatMap(voidMono -> voidMono);//拦截，返回一个提示

    }

    @Override
    public int getOrder() {
        return 1;
    }
}
